package test.springel;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import test.springel.domain.Inventor;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;


/**
 * @author luo
 * @since 2022/8/25 15:01
 */
public class BasicSpringEL {
    ExpressionParser spelExpression = new SpelExpressionParser();

    @DisplayName("基础的解析 ''.bytes 为字节数组")
    @Test
    public void basicParse(){

        Expression expression = spelExpression.parseExpression("'Hello World'.bytes");
        Object value = expression.getValue();
        byte[] bytes = (byte[]) value;
        assertNotNull(bytes);
        assertEquals(new String(bytes),"Hello World");
    }

    @DisplayName("使用 concat() 连接字符串")
    @Test
    public void concatString(){
        Expression expression = spelExpression.parseExpression("'Hello World'.concat(' programmer')");

        String result = (String) expression.getValue();;
        assertNotNull(result);
        assertEquals(result,"Hello World programmer");
    }

    @DisplayName("获取点分隔的属性")
    @Test
    public void getPropertyByDot(){
        Expression expression = spelExpression.parseExpression("'Hello World'.bytes.length");

        Integer strLength = (Integer) expression.getValue();;
        assertNotNull(strLength);
        assertEquals(strLength,11);
    }

    @DisplayName("调用构造器和方法")
    @Test
    public void invokeConstructorAndMethod(){
        Expression expression = spelExpression.parseExpression("new String('Hello World').toUpperCase()");

        String upper = (String) expression.getValue();;
        assertNotNull(upper);
        assertEquals(upper,"HELLO WORLD");
    }

    /**
     * 注意，只能通过get 方法 或者 public 修饰的属性
     */
    @DisplayName("从对象实例中解析属性")
    @Test
    public void resolvePropertyFromObjectInstance(){
        Expression nameExpression = spelExpression.parseExpression("name");

        LocalDateTime birthday = LocalDateTime.of(LocalDate.of(1856, 7, 9), LocalTime.MIN);
        Inventor tesla = new Inventor("Nikola Tesla", birthday, 50);
        String inventorName = (String) nameExpression.getValue(tesla);;
        assertNotNull(inventorName);
        assertEquals(inventorName,"Nikola Tesla");

        Expression ageExpression = spelExpression.parseExpression("age");

        Integer age = (Integer) ageExpression.getValue(tesla);;
        assertNotNull(age);
        assertEquals(age,50);

        Expression birthdayExpression = spelExpression.parseExpression("birthday");

        LocalDateTime parsedBirthday = (LocalDateTime) birthdayExpression.getValue(tesla);;
        assertNotNull(parsedBirthday);
        assertEquals(parsedBirthday.compareTo(birthday),0);
    }
}
